/* A proxy-capable SSL client.

   This is just like sclient but it only supports proxies
*/
#include <string.h>
#include "common.h"
#include "client.h"
#include "read_write.h"

#define PROXY "localhost"
#define PROXY_PORT 8080
#define REAL_HOST "localhost"
#define REAL_PORT 4433

int writestr(sock,str)
  int sock;
  char *str;
  {
    int len=strlen(str);
    int r,wrote=0;
    
    while(len){
      r=write(sock,str,len);
      if(r<=0)
        err_exit("Write error");
      len-=r;
      str+=r;
      wrote+=r;
    }

    return (wrote);
  }

int readline(sock,buf,len)
  int sock;
  char *buf;
  int len;
  {
    int n,r;
    char *ptr=buf;
    
    for(n=0;n<len;n++){
      r=read(sock,ptr,1);
      
      if(r<=0)
        err_exit("Read error");

      if(*ptr=='\n'){
        *ptr=0;

        /* Strip off the CR if it's there */
        if(buf[n-1]=='\r'){
          buf[n-1]=0;
          n--;
        }

        return(n);
      }

      *ptr++;
    }

    err_exit("Buffer too short");      
  }

int proxy_connect(){
    struct hostent *hp;
    struct sockaddr_in addr;
    int sock;
    BIO *sbio;
    char buf[1024];
    char *protocol, *response_code;
    
    /* Connect to the proxy, not the host */
    if(!(hp=gethostbyname(PROXY)))
      berr_exit("Couldn't resolve host");
    memset(&addr,0,sizeof(addr));
    addr.sin_addr=*(struct in_addr*)hp->h_addr_list[0];
    addr.sin_family=AF_INET;
    addr.sin_port=htons(PROXY_PORT);

    if((sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))<0)
      err_exit("Couldn't create socket");
    if(connect(sock,(struct sockaddr *)&addr,sizeof(addr))<0)
      err_exit("Couldn't connect socket");

    /* Now that we're connected, do the proxy request */
    sprintf(buf,"CONNECT %s:%d HTTP/1.0\r\n\r\n",REAL_HOST,REAL_PORT);
    writestr(sock,buf);

    /* And read the response*/
    if(readline(sock,buf,sizeof(buf))==0)
      err_exit("Empty response from proxy");

    if((protocol=strtok(buf," "))<0)
      err_exit("Couldn't parse server response: getting protocol");
    if(strncmp(protocol,"HTTP",4))
      err_exit("Unrecognized protocol");
    if((response_code=strtok(0," "))<0)
      err_exit("Couldn't parse server response: getting response code");
    if(strcmp(response_code,"200"))
      err_exit("Received error from proxy server");
    
    /* Look for the blank line that signals end of header*/
    while(readline(sock,buf,sizeof(buf))>0) {
      ;
    }

    return(sock);
}

int main(argc,argv)
  int argc;
  char **argv;
  {
    SSL_CTX *ctx;
    SSL *ssl;
    BIO *sbio;
    int sock;
    
    /* Build our SSL context*/
    ctx=initialize_ctx(KEYFILE,PASSWORD);

    /* Connect the TCP socket*/
    sock=proxy_connect();

    /* Connect the SSL socket */
    ssl=SSL_new(ctx);
    sbio=BIO_new_socket(sock,BIO_NOCLOSE);    
    SSL_set_bio(ssl,sbio,sbio);
    if(SSL_connect(ssl)<=0)
      berr_exit("SSL connect error");
    check_cert_chain(ssl,HOST);

    /* read and write */
    read_write(ssl,sock);

    destroy_ctx(ctx);
  }

